package edu.washington.cs.pomdb;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import edu.washington.cs.pomdb.ExpCtrl.Actions;
import edu.washington.cs.pomdb.gui.GUI;
/**
 * @author Yanping Huang
 *
 */
public class User {
	private String userName;
	String passwd;
	private double balance;
	private int [] propRight = new int[ExpCtrl.coherenceLevels.length];
	private int [] propLeft = new int[ExpCtrl.coherenceLevels.length];
	int [] numCorrect = new int[ExpCtrl.coherenceLevels.length];
	int [] numInCorrect = new int[ExpCtrl.coherenceLevels.length];
	private double [] rtCorrect = new double[ExpCtrl.coherenceLevels.length];
	private double [] rtInCorrect = new double[ExpCtrl.coherenceLevels.length];
	ArrayList<Trial> trialRecords;
	int totalRuns;

	public User(){
		this("guest");
	}

	
	public User(String name){
		//TODO check if name is already in the database
		userName = name;
		passwd = "null";
		//TODO implement passwd check
		balance = 0;
		trialRecords = new ArrayList<Trial>();
		totalRuns = 0;
	}
	
	public String getUserName(){
		return userName;
	}
	
	public int[] getPropRight(){
		return propRight;
	}
	
	public int[] getPropLeft(){
		return propLeft;
	}
	
	public double[] getRTCorrect(){
		return rtCorrect;
	}
	
	public double[] getRTInCorrect(){
		return rtInCorrect;
	}
	public double getBalance(){
		return balance;
	}
	
	public int getNumTrials(){
		return totalRuns;
	}
	
	public void updateStat(double coherence, Actions answer, boolean isCorrect, int reactionTime, double r){
		int i = ExpCtrl.findCohrence(coherence);
		if(i == -1)//not in coherenceLevels;
			return;
		if(answer == ExpCtrl.Actions.A_R)
			propRight[i]++;
		else
			propLeft[i]++;
		
		if(isCorrect == true){
			numCorrect[i]++;
			rtCorrect[i] = rtCorrect[i] * (numCorrect[i] - 1) / numCorrect[i] + 1.0 * reactionTime / numCorrect[i];
		}
		else{
			numInCorrect[i]++;
			rtInCorrect[i] = rtInCorrect[i] * (numInCorrect[i] - 1) / numInCorrect[i] + 1.0 * reactionTime / numInCorrect[i];
		}
		balance += r;
		totalRuns++;
	}

	public boolean newTrial(int i){
		Trial t = new Trial(userName);
		double c = ExpCtrl.coherenceLevels[i];
		t.setCohrence(c);
		t.start();
		if(t.isFinished()){
			trialRecords.add(t);
			updateStat(t.coherence, t.answer, t.isCorrect, t.reactionTime, t.totalReward);
		}
		return GUI.showTrialResult(t.isCorrect, t.totalReward, this.balance);
	}

//TODO makes saevData append 
	
	public void saveFile(){
		try {
			boolean append = true;
			PrintWriter out = new PrintWriter(
					new FileWriter(new File(userName + ".txt").getAbsoluteFile(),append));
			out.print(printHistory());
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	static User loadFile(String uname){
		User u = new User(uname);
		try {
			BufferedReader in= new BufferedReader(new FileReader(
					new File(uname + ".txt").getAbsoluteFile()));
			try {
				String s;
				while((s = in.readLine()) != null) {
					String [] results = s.split("\\s+");
					if(results.length < 8)
						continue;
					Trial t = new Trial(uname);
					for(int i = 0; i < results.length; i++){
						results[i] = results[i].substring(results[i].lastIndexOf("=")+1);
					}			
					t.setCohrence(Double.valueOf(results[0]));
					t.setRewards(Double.valueOf(results[1]), 
							Double.valueOf(results[2]), Double.valueOf(results[3]));
					t.setReactionTime(Integer.valueOf(results[5]));
					
					if(results[6].equals("true"))
						t.setIsCorrect(true);
					else
						t.setIsCorrect(false);
					
					t.setTotalReward(Double.valueOf(results[7]));
					u.updateStat(t.coherence, t.answer, t.isCorrect, t.reactionTime, t.totalReward);
				}
			} finally {
				in.close();
			}
		} catch(IOException e) {
			throw new RuntimeException(e);
		}
		return u;
	}
	@Override
	public String toString() {
		StringBuilder sb =  new StringBuilder();
		sb.append("UserName=" + userName + "\t Current Balance=" + balance +  "\tTotal trials run=" + getNumTrials() + "\n");
		
		sb.append("Coherence Values\n");
		for(double c : ExpCtrl.coherenceLevels)
			sb.append(c + " ");
		sb.append("\n");
		
		sb.append("Proption Left as a function of coherence \n");
		for(int pl : propLeft)
			sb.append(pl + " ");
		sb.append("\n");
		
		sb.append("Proption Right as a function of coherence \n");
		for(int pr : propRight)
			sb.append(pr + " ");
		sb.append("\n");

		sb.append("Number of Correct Trials as a function of coherence \n");
		for(int num : numCorrect)
			sb.append(num + " ");
		sb.append("\n");
		
		sb.append("Number of Incorrect Trials as a function of coherence \n");
		for(int num : numInCorrect)
			sb.append(num + " ");
		sb.append("\n");
		
		sb.append("Mean Reaction Time of correct trials as a function of coherence \n");
		for(double rt : rtCorrect)
			sb.append(rt + " ");	
		sb.append("\n");

		sb.append("Mean Reaction Time of incorrect trials as a function of coherence \n");
		for(double rt : rtInCorrect)
			sb.append(rt + " ");
		sb.append("\n");
		return sb.toString();
	}

	public String printHistory() {
		StringBuilder sb =  new StringBuilder();
		for(Trial t : trialRecords)
			sb.append(t);
		return sb.toString();
	}

	public void welcome(){
		GUI.showUserStat("Welcome, ", this);
	}
	
	public void farewell(){
		GUI.showUserStat("Good Bye,", this);
	}
	
}
